home *** CD-ROM | disk | FTP | other *** search
/ TestDrive Windows 1993 Fall / TestDrive Windows 1993 Fall.iso / dbase / samples / library.prg < prev    next >
Encoding:
Text File  |  1993-03-09  |  45.4 KB  |  1,342 lines

  1. ******************************************************************************
  2. * PROGRAM NAME: LIBRARY.PRG
  3. *               LIBRARY OF PROCEDURES COMMON TO ALL BUSINESS PROGRAMS
  4. *               SAMPLE BUSINESS APPLICATION PROGRAM
  5. * LAST CHANGED: 06/20/90 8:00AM
  6. * WRITTEN BY:   Borland International Inc.
  7. ******************************************************************************
  8.  
  9. PROCEDURE Add_new
  10.    * Add new record to database file
  11.    * Erase previous record number from screen
  12.    lAddNew = .T.
  13.    @ 0,65 SAY SPACE(15) COLOR &c_yellow.
  14.    * Display F9 lookup key message, if lookup available
  15.    IF lookup_ok
  16.       DO Sho_look WITH dbf
  17.    ENDIF
  18.    DO Init_fld
  19.    DO Get_data
  20.    READ
  21.    * Erase lookup message from screen
  22.    @ 0,0 SAY SPACE(51)
  23.    * If user didn't enter data into key fields, exit without saving
  24.    IF "" = TRIM(&key.) .OR. READKEY() < 256
  25.        RETURN
  26.    ELSE
  27.       * Each application checks for duplicates if duplicate keys not allowed
  28.       * If duplicate key (when not allowed), exit from add mode without saving
  29.       IF rec_is_dup
  30.          * Reset status flag and exit
  31.          rec_is_dup = .F.
  32.          RETURN
  33.       ELSE
  34.          * Append and save validated record
  35.          DO Sav_data
  36.          GO record_num
  37.       ENDIF
  38.    ENDIF
  39. RETURN
  40.  
  41. PROCEDURE Bar_def
  42.    * Define the main popup OPTION MENU, main_mnu
  43.    mesg = "Press first letter of Menu choice, or highlight and press <Enter>"
  44.    DEFINE POPUP main_mnu FROM 2,58 TO 22,78 MESSAGE mesg
  45.    DEFINE BAR  1 OF main_mnu PROMPT "==  OPTION MENU  ==" SKIP
  46.    DEFINE BAR  2 OF main_mnu PROMPT " Add record"
  47.    DEFINE BAR  3 OF main_mnu PROMPT " Edit record"
  48.    DEFINE BAR  4 OF main_mnu PROMPT " Delete record"
  49.    DEFINE BAR  5 OF main_mnu PROMPT "-------------------" SKIP
  50.    DEFINE BAR  6 OF main_mnu PROMPT " Next record"
  51.    DEFINE BAR  7 OF main_mnu PROMPT " Previous record"
  52.    DEFINE BAR  8 OF main_mnu PROMPT " Top record"
  53.    DEFINE BAR  9 OF main_mnu PROMPT " Bottom record"
  54.    DEFINE BAR 10 OF main_mnu PROMPT " Skip records"
  55.    DEFINE BAR 11 OF main_mnu PROMPT " Find record"
  56.    DEFINE BAR 12 OF main_mnu PROMPT "-------------------" SKIP
  57.    DEFINE BAR 13 OF main_mnu PROMPT " List records"
  58.    DEFINE BAR 14 OF main_mnu PROMPT " Output reports"
  59.    DEFINE BAR 15 OF main_mnu PROMPT " Group records" SKIP FOR dbf = "ACCT_REC"
  60.    DEFINE BAR 16 OF main_mnu PROMPT " Count records"
  61.    DEFINE BAR 17 OF main_mnu PROMPT " Index database"
  62.    DEFINE BAR 18 OF main_mnu PROMPT " Help"
  63.    DEFINE BAR 19 OF main_mnu PROMPT " Quit to MAIN MENU"
  64.    * Define the popup dest_mnu for printing reports to a destination
  65.    DEFINE POPUP dest_mnu FROM 13,10 TO 19,38 MESSAGE mesg
  66.    DEFINE BAR 1 OF dest_mnu PROMPT "======= DESTINATION =======" SKIP
  67.    DEFINE BAR 2 OF dest_mnu PROMPT " Printer"
  68.    DEFINE BAR 3 OF dest_mnu PROMPT " File"
  69.    DEFINE BAR 4 OF dest_mnu PROMPT " Screen"
  70.    DEFINE BAR 5 OF dest_mnu PROMPT " Exit to OPTION MENU"
  71.    * Define the popup rpt_mnu for printing reports to a destination
  72.    DEFINE POPUP rpt_mnu FROM 11, 5 TO 17,38 MESSAGE mesg
  73.    DEFINE BAR 1 OF rpt_mnu  PROMPT "============ REPORTS ===========" SKIP
  74.    DEFINE BAR 2 OF rpt_mnu  PROMPT " Database report: " + dbf
  75.    DEFINE BAR 3 OF rpt_mnu  PROMPT " Mailing list: "  + mlist ;
  76.       SKIP FOR mlist = "NOT AVAILABLE"
  77.    DEFINE BAR 4 OF rpt_mnu  PROMPT " Custom programmed report: " + cust_rpt ;
  78.       SKIP FOR cust_rpt = "N/A"
  79.    DEFINE BAR 5 OF rpt_mnu  PROMPT " Exit to OPTION MENU"
  80.    * Define which procedures are executed by the defined popups
  81.    ON SELECTION POPUP main_mnu DO Barpop
  82.    ON SELECTION POPUP rpt_mnu  DO Barpop_r
  83.    ON SELECTION POPUP dest_mnu DO Barpop_d
  84.    * Define windows for text, msgs, etc.
  85.    IF "MONO" $ SET( "DISPLAY" )
  86.       DEFINE WINDOW alert      FROM 15, 3 TO 22,46 DOUBLE COLOR &c_alert.
  87.       DEFINE WINDOW duplicat   FROM 15, 5 TO 21,70 DOUBLE COLOR &c_alert.
  88.       DEFINE WINDOW lister     FROM  5, 5 TO 22,70 DOUBLE COLOR &c_list.
  89.       DEFINE WINDOW look       FROM  6, 5 TO 16,65 DOUBLE COLOR &c_list.
  90.       DEFINE WINDOW memo_windo FROM  7, 4 TO 19,75 DOUBLE COLOR &c_list.
  91.    ELSE
  92.       DEFINE WINDOW alert      FROM 15, 3 TO 22,46 PANEL COLOR &c_alert.
  93.       DEFINE WINDOW duplicat   FROM 15, 5 TO 21,70 PANEL COLOR &c_alert.
  94.       DEFINE WINDOW lister     FROM  5, 5 TO 22,70 PANEL COLOR &c_list.
  95.       DEFINE WINDOW look       FROM  6, 5 TO 16,65 PANEL COLOR &c_list.
  96.       DEFINE WINDOW memo_windo FROM  7, 4 TO 19,75 PANEL COLOR &c_list.
  97.    ENDIF
  98. RETURN
  99.  
  100. PROCEDURE Barpop
  101.    * Perform action selected by user from OPTION MENU bars
  102.    DO CASE
  103.        * BAR() = 1 is title of menu
  104.        CASE BAR() = 2                  && Add record
  105.           DO Add_new
  106.        CASE BAR() = 3                  && Edit record
  107.           DO Edit
  108.        CASE BAR() = 4                  && Delete record
  109.           DO Eraser
  110.        CASE BAR() = 6                  && Next record
  111.           DO Skip_rec WITH 1
  112.        CASE BAR() = 7                  && Previous record
  113.           DO Skip_rec WITH -1
  114.        CASE BAR() = 8                  && Top record, in active index order
  115.           GO TOP
  116.        CASE BAR() = 9                  && Bottom record, in active index order
  117.           GO BOTTOM
  118.        CASE BAR() = 10                 && Skip records
  119.           DO Skip_rec WITH 0
  120.        CASE BAR() = 11                 && Find record
  121.           DO Find_rec WITH key, key1, keyname1, key2, keyname2, key3, keyname3
  122.        CASE BAR() = 13                 && List records
  123.           DO List_rec
  124.        CASE BAR() = 14                 && Output reports
  125.           SAVE SCREEN TO Pre_rept      && Save screen image
  126.           ACTIVATE POPUP rpt_mnu
  127.           RESTORE SCREEN FROM Pre_rept
  128.           RELEASE SCREEN Pre_rept
  129.        CASE BAR() = 15              && Group records
  130.           DO Filter
  131.        CASE BAR() = 16                 && Count records
  132.           ************
  133.           IF NETWORK()
  134.              * Turn off file lock to count
  135.              SET LOCK off
  136.              DO Kount
  137.              SET LOCK on
  138.              ***********
  139.           ELSE
  140.              DO Kount
  141.           ENDIF
  142.        CASE BAR() = 17                  && Index database
  143.           ************
  144.           IF NETWORK()
  145.              old_tag = ORDER()
  146.              USE (dbf) EXCLUSIVE
  147.              IF net_choice <> 27        && check Net_err user choice (Esc=27)
  148.                 DO Indexer
  149.                 SET EXCLUSIVE off
  150.                 USE (dbf) ORDER (old_tag)
  151.              ENDIF
  152.              ***********************
  153.           ELSE
  154.              DO Indexer
  155.           ENDIF
  156.        CASE BAR() = 18                  && Help
  157.           SET COLOR TO &c_standard.
  158.           DO Helper
  159.        CASE BAR() = 19                && Quit to Main Menu
  160.           DEACTIVATE POPUP
  161.    ENDCASE
  162.    DO Dstatus                         && Display record no and filter status
  163.    DO Show_data                       && Display screen with current record
  164.    CLEAR GETS
  165.    SET COLOR TO &c_popup.
  166. RETURN
  167.  
  168. PROCEDURE Barpop_d
  169.    * Perform action selected by user from Destination menu
  170.    SET COLOR TO &c_popup.
  171.    DO CASE
  172.       * BAR() 1 is title of menu
  173.       CASE BAR() = 2                  && Output to printer
  174.          ll_esc = .F.
  175.          DO Prt_menu                  && Activate menu for print options
  176.          IF .NOT. ll_esc
  177.             SET PRINTER on
  178.             SET CONSOLE off
  179.             DO Printout               && Output selected report
  180.             SET PRINTER off
  181.             SET CONSOLE on
  182.          ENDIF
  183.       CASE BAR() = 3                  && Output to file
  184.          answer = SPACE(8)
  185.          ACTIVATE WINDOW alert
  186.             @ 0,0 SAY "----------- SEND REPORT TO FILE ----------"
  187.             @ 2,1 SAY "Enter filename for report: " GET answer ;
  188.                VALID "" <> TRIM(answer) ;
  189.                MESSAGE "Enter a filename of up to eight characters"
  190.             READ
  191.          DEACTIVATE WINDOW alert
  192.          SET ALTERNATE TO &answer.
  193.          SET ALTERNATE on
  194.          SET CONSOLE off
  195.          GO TOP
  196.          DO Printout                  && Output report or labels to file
  197.          SET ALTERNATE off
  198.          SET CONSOLE on
  199.       CASE BAR() = 4                  && Output to screen
  200.          SET COLOR TO &c_standard.
  201.          CLEAR
  202.          * Store current page settings
  203.          plength  = _plength
  204.          rmargin  = _rmargin
  205.          * Set page width & length for screen
  206.          _plength = 25
  207.          _rmargin = 80
  208.          DO Printout                  && Output chosen report/labels to screen
  209.          CLEAR
  210.          * Reset page settings
  211.          _plength = plength
  212.          _rmargin = rmargin
  213.          GO record_num                && Return to original record
  214.       CASE BAR() = 5                  && Exit to OPTION MENU
  215.          DEACTIVATE POPUP
  216.    ENDCASE
  217.    SET COLOR TO &c_standard.
  218.    DEACTIVATE POPUP
  219. RETURN
  220.  
  221. PROCEDURE Barpop_r
  222.    * Select available reports menu
  223.    SET COLOR TO &c_popup.
  224.    reportype = SPACE(6)
  225.    DO CASE
  226.       CASE BAR() = 2                  && Output standard report to destination
  227.          reportype = "LISTING"
  228.          ACTIVATE POPUP dest_mnu      && Activate printer destination menu
  229.       CASE BAR() = 3                  && Output mailing labels to destination
  230.          reportype = "LABELS"
  231.          ACTIVATE POPUP dest_mnu      && Activate printer destination menu
  232.       CASE BAR() = 4                  && Output custom report to destination
  233.          reportype = "CUSTOM"
  234.          ACTIVATE WINDOW alert
  235.             * Get custom report name from user
  236.             * First, allow READ errors and warning bell
  237.             SET BELL ON
  238.             rpt_name = SPACE(8)
  239.             @ 0,0 SAY "-------- CUSTOM PROGRAMMED REPORT --------"
  240.             @ 2,1 SAY "Enter report program name:" GET rpt_name ;
  241.                VALID FILE(TRIM(rpt_name) + ".prg") ;
  242.                MESSAGE "Enter a filename of up to eight " + ;
  243.                        "characters, e.g. Emp_rept " ;
  244.                ERROR "Invalid filename, please re-enter"
  245.             READ
  246.             SET BELL OFF
  247.          DEACTIVATE WINDOW alert
  248.          IF LASTKEY() <> 27           && A report filename was found
  249.             SET COLOR TO &c_popup.
  250.             ACTIVATE POPUP dest_mnu
  251.          ENDIF
  252.    ENDCASE
  253.    SET COLOR TO &c_popup.
  254.    DEACTIVATE POPUP
  255. RETURN
  256.  
  257. PROCEDURE Sub_ret
  258.    IF erased
  259.       * Pack deleted records (if any) - erases completely from database
  260.       ************
  261.       IF NETWORK()
  262.          USE (dbf) EXCLUSIVE
  263.       ENDIF
  264.       IF net_choice <> 27       && Skip if user pressed Esc
  265.       *******************       && error condition
  266.          ?? CHR(7)
  267.          ACTIVATE WINDOW alert
  268.             @ 0,0 SAY "----------- PACKING  DATABASE ------------"
  269.             @ 2,1 SAY "ERASING deleted records now......"
  270.             @ 3,1 SAY "Please wait......DO NOT TURN OFF"
  271.             PACK
  272.          DEACTIVATE WINDOW alert
  273.       ENDIF
  274.    ENDIF
  275.    * Houskeeping
  276.    CLOSE DATABASES
  277.    CLEAR WINDOWS
  278.    RELEASE ALL
  279.    CLEAR
  280.    ON KEY LABEL F9             && Turn off ON KEY LABEL F9/F10 commands
  281.    ON KEY LABEL F10
  282.    * Restore environment (in case user began at Control Center or dot prompt)
  283.    DO Rest_env
  284.    CLEAR
  285. RETURN TO MASTER               && Exit Subapplication
  286.  
  287. FUNCTION Duplicat
  288.    PARAMETERS key
  289.    * Used if duplicates are not allowed in a database
  290.    * Set rec_is_dup to .T. if user entered duplicate key data
  291.    rec_is_dup = .F.
  292.    IF RECCOUNT() = 0 .OR. "" = TRIM(key)
  293.       * Do not check if database or key field(s) is empty
  294.       RETURN rec_is_dup
  295.    ENDIF
  296.    record_num = RECNO()               && Save current record position
  297.    SEEK  TRIM(key)
  298.    * Determine if record is duplicate key
  299.    * PROMPT() used instead of BAR() for clarity
  300.    DO CASE
  301.       CASE PROMPT() = " Edit record"
  302.          * If seek finds a record other than the current one,
  303.          * the edited record has a duplicate key
  304.          rec_is_dup =  record_num <> RECNO() .AND. FOUND()
  305.       CASE PROMPT() = " Add record"
  306.          * New record is duplicate if seek finds any record that matches
  307.          rec_is_dup = FOUND()
  308.    ENDCASE
  309.    IF rec_is_dup                      && Show duplicate record in window
  310.       ACTIVATE WINDOW duplicat
  311.          CLEAR
  312.          DO Warnbell
  313.          ?  "------------------ DUPLICATE " + dbf + ;
  314.             " RECORD ------------------"
  315.          ?  "                    Duplicates not allowed"
  316.          DO CASE
  317.             CASE dbf = "CUST"
  318.                ?  " " + cust_id + " " + customer
  319.                ? "This is the EXISTING record in the database; " + ;
  320.                  "re-enter Cust.ID."
  321.             CASE dbf = "VENDORS"
  322.                ?  " " + vendor_id + " " + vendor
  323.                ? "This is the EXISTING record in the database; " + ;
  324.                  "re-enter Vendor ID."
  325.             CASE dbf = "GOODS"
  326.                ?  " " + part_id + " " + part_name
  327.                ? "This is the EXISTING record in the database; " + ;
  328.                  "re-enter Part ID."
  329.             CASE dbf = "ACCT_REC"
  330.                ?  " " + invoice_no + " " + cust_id + " " + DTOC(dat_of_bil)
  331.                ? "This is the EXISTING record in the database; " + ;
  332.                  "re-enter Invoice ID."
  333.          ENDCASE
  334.          WAIT "     Press spacebar to continue..."
  335.       DEACTIVATE WINDOW duplicat
  336.    ENDIF
  337.    GO record_num                     && Return to original record
  338. RETURN .NOT. rec_is_dup
  339.  
  340. PROCEDURE Dstatus
  341.    * Display filter status and current record number
  342.    * Set colors with blink on/off depending on hardware
  343.    IF filters_on
  344.       * Show blinking msg for filter status
  345.       @ 0,51 SAY "Filter is ON" COLOR &c_blink.
  346.    ELSE
  347.       SET COLOR TO &c_standard.
  348.       * Erase message - filter is off
  349.       @ 0,51
  350.    ENDIF
  351.    * Show  current record number on screen
  352.    @ 0,66 SAY "Record #" + STR(RECNO(),5,0) COLOR &c_yellow.
  353. RETURN
  354.  
  355. PROCEDURE Edit
  356.    * Edit current record
  357.    * Display lookup key message if lookup available (set in each application)
  358.    lAddNew = .F.
  359.    IF lookup_ok
  360.       DO Sho_look WITH dbf
  361.    ENDIF
  362.    record_num = RECNO()
  363.    * Load data from record into memory variables
  364.    DO Load_fld
  365.    IF NETWORK()                      && Edit data in a network
  366.       ready = .F.
  367.       DO WHILE .NOT. ready
  368.          IF CHANGE()
  369.             * If the record was changed by somone since user first accessed it
  370.             DO Warnbell
  371.             GO RECNO()           && Updates database record with changed data
  372.             IF DELETED()
  373.                DO Show_msg WITH "ALERT - Record has been deleted"
  374.                SKIP
  375.                DO Show_data
  376.                RETURN            && Exit to OPTION MENU - quit edit
  377.             ELSE
  378.                DO Show_msg WITH ;
  379.                   "Data has been changed-screen shows revised data"
  380.                DO Load_fld           && Updates memvars with database data
  381.             ENDIF
  382.          ENDIF
  383.          DO Get_data
  384.          READ                        && Edit data
  385.          * Test if another user changed data while editing this data
  386.          ready = .NOT. CHANGE()      && DO loop will repeat if CHANGE() is .F.
  387.       ENDDO
  388.    ELSE                              && Non-network edit
  389.       DO Get_data
  390.       READ                           && Edit data
  391.    ENDIF
  392.    *****
  393.    * Erase F9 lookup message from screen
  394.    @ 0,0 SAY SPACE(51)
  395.    IF "" = TRIM(&key.) .OR. READKEY() < 256
  396.       * Exit if user blanked key, did not change data, or deleted record
  397.       RETURN
  398.    ELSE
  399.       * Save edited data to disk
  400.       DO Sav_data
  401.    ENDIF
  402. RETURN
  403.  
  404. PROCEDURE Eraser
  405.    * Erase current record
  406.    IF NodShake( " ;   Erase this data record?   ", ;
  407.                 9, 26, 2, 29, .F. )
  408.  
  409.       DELETE
  410.       * Position to the next record
  411.       SKIP
  412.       * Check if the last record was deleted
  413.       DO CASE
  414.          CASE filters_on .AND. EOF()
  415.             * If no records left in filter subset, turn off filter
  416.             SET FILTER TO
  417.             filters_on = .F.
  418.             * If last record deleted, go to beginning of database
  419.             GO TOP
  420.          CASE .NOT. filters_on .AND. EOF()
  421.             * If last record deleted, go to beginning of database
  422.             GO TOP
  423.       ENDCASE
  424.       * Set erased status flag that record was deleted
  425.       erased = .T.
  426.    ENDIF
  427. RETURN
  428.  
  429. PROCEDURE Filt_ans
  430.    * Get answer from user about filtering data into subset
  431.    IF filters_on
  432.       *-- Filter window - to turn off filter
  433.       IF NodShake( " ;    GROUP into SUBSET (Filter)   ;" + ;
  434.                    "   Subset is currently selected.   ;" + ;
  435.                    "         Turn Filter off?", ;
  436.                    7, 22, 4, 35, .F. )
  437.          choice = "T"
  438.       ELSE
  439.          choice = "N"
  440.       ENDIF
  441.    ELSE
  442.       *-- Filter window - to turn on filter
  443.       IF NodShake( " ;    GROUP into SUBSET (Filter)   ;" + ;
  444.                    "   Select temporary subset of data   ;" + ;
  445.                    "   by entering filter condition(s)   ;" + ;
  446.                    "             Proceed?", ;
  447.                    7, 21, 5, 37, .F. )
  448.          choice = "Y"
  449.       ELSE
  450.          choice = "N"
  451.       ENDIF
  452.  
  453.    ENDIF
  454. RETURN
  455.  
  456. PROCEDURE Findcode
  457.    PARAMETERS acity
  458.    * Look up area code for phone number - by city
  459.    acode = 0
  460.    ACTIVATE WINDOW alert
  461.       CLEAR
  462.       acode = LOOKUP(Codes->code,TRIM(acity),Codes->city)
  463.       ? "------------- AREA CODE LOOKUP -----------"
  464.       IF .NOT. FOUND("Codes") .OR. "" = TRIM(acity)
  465.          DO Warnbell
  466.          ? "City: " + TRIM(acity) + " was"    AT 2
  467.          ? "NOT FOUND in areacodes database." AT 2
  468.       ELSE
  469.          ?
  470.          ? "AREA CODE is: " + STR(acode,3) AT 2
  471.          ? "for " + TRIM(acity)  AT 16
  472.       ENDIF
  473.       ?
  474.       WAIT "  Press spacebar to continue..."
  475.    DEACTIVATE WINDOW alert
  476. RETURN
  477.  
  478. PROCEDURE Findcust
  479.    PARAMETERS custid
  480.    * Look up customer from customer ID
  481.    acust = ""
  482.    ACTIVATE WINDOW alert
  483.       CLEAR
  484.       acust = LOOKUP(Cust->customer,TRIM(custid),Cust->cust_id)
  485.       ? "---------- CUSTOMER ID  LOOKUP -----------"
  486.       IF .NOT. FOUND("Cust") .OR. "" = TRIM(custid)
  487.          DO Warnbell
  488.          ? "Customer ID: " + TRIM(custid) + " was" AT 2
  489.          ? "NOT FOUND in Cust database." AT 2
  490.       ELSE
  491.          ? "Customer: " + TRIM(acust)  AT 2
  492.          ? "Phone:    " + Cust->phone  AT 2
  493.          ? "for ID: "   + TRIM(custid) AT 12
  494.       ENDIF
  495.       WAIT "  Press spacebar to continue..."
  496.    DEACTIVATE WINDOW alert
  497. RETURN
  498.  
  499. PROCEDURE Find_rec
  500.    PARAMETERS key, key1, keyname1, key2, keyname2, key3, keyname3
  501.    * Get target data to find/seek and show data record after retrieving
  502.    STORE "" TO target1, target2, target3
  503.    target1 = IIF(TYPE(key1) = "C", SPACE(LEN(&key1.)), {  /  /  })
  504.    * If key2 exists (database requires two keys)
  505.    IF "NONE" <> key2
  506.       target2 = IIF(TYPE(key2) = "C", SPACE(LEN(&key2.)), {  /  /  })
  507.       * If key3 exists (database has three keys)
  508.       IF "NONE" <> key3
  509.          target3 = IIF(TYPE(key3) = "C", SPACE(LEN(&key3.)), {  /  /  })
  510.       ENDIF
  511.    ENDIF
  512.    ACTIVATE WINDOW alert
  513.       @ 0,0 SAY "-------- ENTER TARGET DATA TO FIND -------"
  514.       @ 2, 1 SAY keyname1
  515.       @ 2,15 GET target1  MESSAGE "Enter " + keyname1
  516.       IF "NONE" <> key2
  517.          @ 3, 1 SAY keyname2
  518.          @ 3,15 GET target2
  519.          IF "NONE" <> key3
  520.             @ 4, 1 SAY keyname3
  521.             @ 4,15 GET target3
  522.          ENDIF
  523.       ENDIF
  524.       @ 5,1 SAY "Enter partial or entire data"
  525.       READ
  526.    DEACTIVATE WINDOW alert
  527.    target = IIF(type(key1) = "C", target1, DTOC(target1))
  528.    IF "NONE" <> key2
  529.       target = target + IIF(type(key2) = "C", target2, DTOC(target2))
  530.       IF "NONE" <> key3
  531.          target = target + IIF(type(key3) = "C", target3, DTOC(target3))
  532.       ENDIF
  533.    ENDIF
  534.    target = TRIM(target)
  535.    IF RIGHT(target, 6) = "  /  /"
  536.       * If a date key wasn't filled in, remove the template
  537.       target = LEFT(target, LEN(target) - 6)
  538.    ENDIF
  539.    IF "" = target
  540.       * If user entered nothing (blank key) => exit
  541.       RETURN
  542.    ENDIF
  543.    * Store record no. that the user was viewing
  544.    record_num = RECNO()
  545.    * Find record with target key
  546.    IF .NOT. SEEK(target)
  547.       * If target not found, uppercase & look again
  548.       IF .NOT. SEEK(UPPER(target))
  549.          * Sound bell and alert user with message
  550.          DO Warnbell
  551.          DO Show_msg WITH "Record with target data was NOT found."
  552.          * Return to original record user was viewing
  553.          GO record_num
  554.       ENDIF
  555.    ENDIF
  556. RETURN
  557.  
  558. PROCEDURE Findpart
  559.    PARAMETERS partid
  560.    * Look up part data using part ID number in Goods database when
  561.    * function key pressed
  562.    p_name = SPACE(30)
  563.    ACTIVATE WINDOW alert
  564.       CLEAR
  565.       p_name = LOOKUP(Goods->part_name,TRIM(partid),Goods->part_id)
  566.       ? "------------ PART CODE  LOOKUP ----------"
  567.       IF .NOT. FOUND("Goods") .OR. "" = TRIM(partid)
  568.          DO Warnbell
  569.          ? "Part ID: " + TRIM(partid) AT 2
  570.          ? "was NOT FOUND in Goods database." AT 2
  571.       ELSE
  572.          ? "For ID:    " + partid       AT 2
  573.          ? "Part name: " + TRIM(p_name) AT 2
  574.          ? "Qty on hand: " + STR(Goods->qty_onhand,4) AT 2
  575.          ? "Price: $  " AT 2, Goods->price PICTURE "99,999.99"
  576.       ENDIF
  577.       WAIT " .....Press spacebar to continue....."
  578.    DEACTIVATE WINDOW alert
  579. RETURN
  580.  
  581. PROCEDURE Findvend
  582.    PARAMETERS vendr
  583.    * Look up vendor name using vendor ID number in Vendor database
  584.    * when function key pressed
  585.    v_name = SPACE(30)
  586.    ACTIVATE WINDOW alert
  587.       CLEAR
  588.       v_name = LOOKUP(Vendors->vendor,TRIM(vendr),Vendors->vendor_id)
  589.       ? "----------- VENDOR CODE LOOKUP -----------"
  590.       IF .NOT. FOUND("Vendors")
  591.          DO Warnbell
  592.          ? "Vendor ID: " + TRIM(vendr)    AT 2
  593.          ? "was NOT FOUND in Vendors database." AT 2
  594.       ELSE
  595.          ? "VENDOR is: " + TRIM(v_name)   AT 2
  596.          ? "Phone:     " + Vendors->phone AT 2
  597.          ? "for ID:  "   + vendr          AT 16
  598.       ENDIF
  599.       WAIT "   Press spacebar to continue..."
  600.    DEACTIVATE WINDOW alert
  601. RETURN
  602.  
  603. PROCEDURE Kount
  604.    * Count and display number of records in database
  605.    record_num = RECNO()
  606.    ACTIVATE WINDOW alert
  607.      @ 0,0 SAY "------------- COUNT  RECORDS -------------"
  608.      @ 2,1 SAY "Counting, please wait..."
  609.      * Use count if filter is active (subset of records)
  610.      COUNT TO kount
  611.      @ 2,1 SAY "There are: " + STR (kount,6) + " records in "+ dbf
  612.      ?
  613.      WAIT " Press any key to continue..."
  614.    DEACTIVATE WINDOW alert
  615.    * Return to original record (before count)
  616.    GO record_num
  617. RETURN
  618.  
  619. PROCEDURE List_rec
  620.    * Lists records (in active index order) from current record on
  621.    * If filter is active, then subset listed
  622.    lEscape = SET("ESCAPE") = "ON"
  623.    SET ESCAPE OFF
  624.    record_num = RECNO()                 && Store current record position
  625.    GO TOP
  626.    ACTIVATE WINDOW lister
  627.       answer = " "
  628.       CLEAR
  629.       @ 0,0 SAY "------------------------- LIST RECORDS " + ;
  630.                 "-------------------------" ;
  631.             COLOR &c_red.
  632.       SCAN WHILE .NOT. answer $ "rR"
  633.          LIST OFF NEXT 10 &list_flds.
  634.          WAIT "Press spacebar to continue or R to return to " + ;
  635.               "OPTION MENU." TO answer
  636.          CLEAR
  637.       ENDSCAN
  638.    DEACTIVATE WINDOW lister
  639.    IF lEscape
  640.       SET ESCAPE OFF
  641.    ENDIF
  642.    * Return to original record (before viewing list)
  643.    GO record_num
  644. RETURN
  645.  
  646. PROCEDURE Look_msg
  647.    DO CASE                                && Show proper lookup msg in window
  648.       CASE similar = .F.                  && No similar data found
  649.          @ 1,1 SAY "Entered "+look_name+" ID does not exist in " + ;
  650.                look_dbf+" database."
  651.          ?
  652.          WAIT "No " + look_name + " ID's are similar - " + ;
  653.               "press R to return to screen." TO answer
  654.       CASE similar = .T. .AND. listcount > 0
  655.          && Similar data found and listed
  656.          WAIT "Press spacebar to continue list or " + ;
  657.               "R to return to screen." TO answer
  658.          CLEAR
  659.    ENDCASE
  660.    CLEAR
  661. RETURN
  662.  
  663. FUNCTION Lookupid
  664.    PARAMETERS l_target, look_dbf, look_name, matchchars
  665.    * During data entry or editing, validate data entered into any of the
  666.    * fields of customer ID, parts ID, vendor ID, and employee ID by checking
  667.    * for their existence in their respective databases - list any similar data
  668.    * by matching the first one or more characters (between entered data and
  669.    * database).
  670.    * Note: matchchars = number of initial matching characters for lookup lists
  671.    * Example: list will show customers whose cust_id's first two characters
  672.    * match with the entered cust_id's first two characters (matchchars = 2)
  673.    IF .NOT. SEEK(l_target,(look_dbf))     && Seek data in its respective dbf
  674.       ACTIVATE WINDOW look
  675.       DO Warnbell
  676.       answer = " "
  677.       similar = .F.
  678.       SELECT (look_dbf)                   && Use appropriate dbf for listing
  679.       GO TOP
  680.       DO WHILE .NOT. (EOF() .OR. answer $ "rR")
  681.          * Show list of records having identical initial character(s)
  682.          * in ID number
  683.          @ 0,0 SAY "-------- DATA ENTRY ERROR: " + look_name + ;
  684.                    " ID WAS INVALID -------"
  685.          @ 1,0 SAY "          This is a list of similar " + look_name + ;
  686.                    " ID's"
  687.          ?
  688.          listcount = 0
  689.          DO CASE                         && Check which database screen in use
  690.            CASE dbf = "ORDERS"
  691.               DO CASE                    && Check which field is being read
  692.                  CASE VARREAD() = "CUST_ID"
  693.                     SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",cust_id) ;
  694.                        WHILE listcount <= 4
  695.                        ? cust_id, customer           && Display a record
  696.                        listcount = listcount + 1     && Increment list counter
  697.                        similar = .T.                 && Data found and listed
  698.                     ENDSCAN
  699.                  CASE VARREAD() = "PART_ID"
  700.                     SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",part_id) ;
  701.                        WHILE listcount <= 4
  702.                        ? part_id, SUBSTR(part_name,1,21), ;
  703.                          SUBSTR(descript,1,24)
  704.                        listcount = listcount + 1     && Increment list counter
  705.                        similar = .T.                 && Data found and listed
  706.                     ENDSCAN
  707.                  CASE VARREAD() = "EMP_ID"
  708.                     SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",emp_id) ;
  709.                        WHILE listcount <= 4
  710.                        ? emp_id, lastname, firstname && Display a record
  711.                        listcount = listcount + 1     && Increment list counter
  712.                        similar = .T.                 && Data found and listed
  713.                     ENDSCAN
  714.               ENDCASE
  715.            CASE dbf = "GOODS"
  716.               SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",vendor_id) ;
  717.                  WHILE listcount <= 4
  718.                  ? vendor_id, vendor                 && Display a record
  719.                  listcount = listcount + 1           && Increment list counter
  720.                  similar = .T.                       && Data found and listed
  721.               ENDSCAN
  722.            CASE dbf = "ACCT_REC"
  723.               SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",cust_id) ;
  724.                  WHILE listcount <= 4
  725.                  ? cust_id, customer                 && Display a record
  726.                  listcount = listcount + 1           && Increment list counter
  727.                  similar = .T.                       && Data found and listed
  728.               ENDSCAN
  729.          ENDCASE
  730.          DO Look_msg                                 && Show message in window
  731.       ENDDO
  732.       DEACTIVATE WINDOW look
  733.       SELECT 1                                       && Use original dbf
  734.    ENDIF
  735. RETURN not_valid = .NOT. FOUND((look_dbf))
  736.  
  737. PROCEDURE Net_err
  738.    PARAMETERS err_number
  739.    * Error procedure for networks
  740.    DO CASE
  741.       CASE err_number = 108
  742.          * File is in use by another person
  743.          IF "" <> TRIM(LKSYS(2))
  744.             message = " " + dbf + " is in use by: " + LKSYS(2)
  745.          ELSE
  746.             message = " " + dbf + " is in use by someone"
  747.          ENDIF
  748.       CASE err_number = 109
  749.          * Record is locked by another person
  750.          message = " Record is locked by: " + LKSYS(2)
  751.       CASE err_number = 110
  752.          * File must be in exclusive use for indexing/packing
  753.          message = "File should be USEd EXCLUSIVE"
  754.       CASE err_number = 372 .OR. err_number = 373
  755.          * File or record is in use by another
  756.          message = MESSAGE()
  757.       OTHERWISE
  758.          message = " Unknown error: " + MESSAGE()
  759.    ENDCASE
  760.    DO Warnbell
  761.    ACTIVATE WINDOW alert
  762.       CLEAR
  763.       ? "------------ NETWORK ERROR --------------"
  764.       ?
  765.       ? message AT 1
  766.       ? "Press spacebar to try again" AT 1
  767.       ? " - or press Esc to Quit" AT 1
  768.       net_choice = INKEY(0)          && Wait for user to press a key
  769.    DEACTIVATE WINDOW alert
  770.    IF net_choice <> 27               && User did not press Esc key
  771.       * Execute command again that caused network error
  772.       RETRY
  773.    ELSE
  774.       DO Gen_Err WITH ERROR(), MESSAGE()
  775.    ENDIF
  776. RETURN
  777.  
  778. PROCEDURE Printout
  779.    * Print report or label
  780.    DO CASE
  781.       CASE reportype = "LISTING"
  782.          REPORT FORM &dbf.
  783.       CASE reportype = "LABELS"
  784.          LABEL FORM &dbf.
  785.       CASE reportype = "CUSTOM"
  786.          DO &rpt_name.
  787.    ENDCASE
  788.    GO record_num
  789. RETURN
  790.  
  791. PROCEDURE Prt_menu
  792.    * Display menu of print options
  793.    msg_num   = "Enter a number"
  794.    msg_logic = "Enter a Y or N"
  795.    msg_enum  = "Press spacebar for other options"
  796.    * Set up default values to print variables for reports
  797.    loffset  = 0
  798.    lmargin  = 0
  799.    rmargin  = 80
  800.    indent   = 4
  801.    plength  = 66           && 60 - HP laserjet printer
  802.    STORE 1 TO pspacing, pbpage, pcopies
  803.    pepage   = 9999
  804.    peject   = "NONE  "
  805.    STORE .F. TO pwait, pquality
  806.    ppitch   = "PICA     "
  807.    *
  808.    ACTIVATE WINDOW lister
  809.    CLEAR
  810.    @  0, 0 SAY "------------------------- PRINT MENU " + ;
  811.               "---------------------------" COLOR &c_red.
  812.    @  2, 1 SAY "Page settings:"
  813.    @  3, 1 SAY "============="
  814.    @  4, 1 SAY "Offset from left  " GET loffset ;
  815.            PICTURE "99" MESSAGE msg_num
  816.    @  5, 1 SAY "Left margin       " GET lmargin ;
  817.            PICTURE "99" MESSAGE msg_num
  818.    @  6, 1 SAY "Right margin      " GET rmargin ;
  819.            PICTURE "99" MESSAGE msg_num
  820.    @  7, 1 SAY "Indentation       " GET indent ;
  821.            PICTURE "99" MESSAGE msg_num
  822.    @  8, 1 SAY "Page length       " GET plength ;
  823.            PICTURE "99" MESSAGE msg_num
  824.    @  9, 1 SAY "Spacing           " GET pspacing ;
  825.            PICTURE "9"  RANGE 1,3 MESSAGE msg_num
  826.    @  2,26 SAY "Print settings:"
  827.    @  3,26 SAY "=============="
  828.    @  4,26 SAY "Begin printing on page  " GET pbpage ;
  829.            PICTURE "999"  MESSAGE msg_num
  830.    @  5,26 SAY "End printing on page    " GET pepage ;
  831.            PICTURE "9999" MESSAGE msg_num
  832.    @  6,26 SAY "Number of copies        " ;
  833.            GET pcopies  PICTURE "999"  MESSAGE msg_num
  834.    @  7,26 SAY "Eject paper             " GET peject ;
  835.            PICTURE "@M BEFORE,AFTER,BOTH,NONE"  MESSAGE msg_enum
  836.    @  8,26 SAY "Wait between pages      " GET pwait ;
  837.            PICTURE "Y" MESSAGE msg_logic
  838.    @  9,26 SAY "Pitch                   " GET ppitch ;
  839.            PICTURE "@M DEFAULT,PICA,ELITE,CONDENSED" MESSAGE msg_enum
  840.    @ 10,26 SAY "Quality print           " GET pquality ;
  841.            PICTURE "Y" MESSAGE msg_logic
  842.    @ 12, 1 SAY "Please enter desired settings; press Esc to cancel"
  843.    READ
  844.    DEACTIVATE WINDOW lister
  845.    IF LASTKEY() = 27                    && If Escaped presses
  846.       ll_esc = .T.
  847.    ELSE
  848.       ll_esc = .F.
  849.  
  850.       * Assign values to system variables
  851.       _ploffset = loffset
  852.       _lmargin  = lmargin
  853.       _rmargin  = rmargin
  854.       _indent   = indent
  855.       _plength  = plength
  856.       _pspacing = pspacing
  857.       _pbpage   = pbpage
  858.       _pepage   = pepage
  859.       _pcopies  = pcopies
  860.       _peject   = peject
  861.       _pwait    = pwait
  862.       IF PRINTSTATUS()
  863.         _ppitch   = ppitch
  864.       ENDIF
  865.       _pquality = pquality
  866.    ENDIF
  867.    SET COLOR TO &c_standard.
  868. RETURN
  869.  
  870. PROCEDURE Rest_env
  871.    IF TYPE( "gl_MainMenu" ) = "L"
  872.       RETURN
  873.    ENDIF
  874.  
  875.    * Restore database environment
  876.    SET COLOR TO &c_standard.
  877.    SET SCOREBOARD &scor.
  878.    SET DELIMITERS &deli.
  879.    SET HELP &hellp.
  880.    SET ESCAPE &esca.
  881.    SET DELETED &delee.
  882.    SET HEADING &head.
  883.    SET SAFETY &safe.
  884.    SET EXACT &exac.
  885.    SET BELL &bell.
  886.    SET NEAR &near.
  887.    * Reset colors to system defaults
  888.    DO Colo_rese
  889.    SET CLOCK &clock.
  890.    SET STATUS &stat.
  891.    SET TALK &talk.
  892. RETURN
  893.  
  894. PROCEDURE Sav_data
  895.    * If data is new: append record currently in memory to database.
  896.    * If edited/modified data: replace database record with memory fields.
  897.    IF NodShake( " ;   Save this data to disk?   ", ;
  898.                 9, 26, 2, 29, .F. )
  899.       IF lAddNew
  900.          APPEND BLANK
  901.          record_num = RECNO()
  902.       ELSE
  903.          record_num = RECNO()
  904.       ENDIF
  905.       * Replace database file fields with contents of memory variables
  906.       DO Repl_fld
  907.    ELSE
  908.       * Do not save data to disk, return to original record
  909.       GO record_num
  910.    ENDIF
  911. RETURN
  912.  
  913. PROCEDURE Set_env
  914.    IF TYPE( "FILTERS_ON" ) = "L"
  915.       filters_on = .F.
  916.    ENDIF
  917.    IF TYPE( "gl_MainMenu" ) = "L"
  918.       RETURN                            && Setup already done by BUSINESS.PRG
  919.    ENDIF
  920.    PUBLIC talk                  && First set TALK OFF
  921.    IF SET( "TALK" ) = "ON"
  922.       SET TALK OFF
  923.       talk = "ON"
  924.    ELSE
  925.       talk = "OFF"
  926.    ENDIF
  927.  
  928.    PUBLIC c_Save
  929.    c_save = SET( "ATTRIBUTES" )
  930.  
  931.    PUBLIC c_standard, c_data, c_fields, c_popup, c_alert, c_list
  932.    PUBLIC c_red, c_blue, c_yellow, c_yelowhit, c_green, c_blink
  933.  
  934.    * Set color variables for applications
  935.    IF ISCOLOR()
  936.       * Color video card/monitor
  937.       c_standard = "W/B,BG+/R,B"
  938.       c_data     = "B/W,R/BG,B"
  939.       c_fields   = "B/BG"
  940.       c_popup    = "B/W,GR+/R"
  941.       c_alert    = "GR+/R,B/W,R/G"
  942.       c_list     = "W+/G,GR+/B,GR+/GR"
  943.       c_red      = "R/W"
  944.       c_blue     = "B/W"
  945.       c_yellow   = "GR+/B"
  946.       c_yelowhit = "GR+/W"
  947.       c_green    = "G/W"
  948.       c_blink    = "GR+*/B"
  949.    ELSE
  950.       * Monochrome video card/monitor
  951.       STORE "W+/N" TO c_standard, c_data, c_popup, c_alert, c_list
  952.       STORE "W" TO  c_red, c_blue, c_yellow, c_yelowhit, c_green, c_fields
  953.       c_blink = "W+*/N,N/W"
  954.    ENDIF
  955.    SET COLOR OF MESSAGES TO &c_blue.
  956.    SET COLOR TO &c_standard.
  957.  
  958.    * Configure working environment
  959.    * Store SET environment in case started from Control Center or dot prompt
  960.    PUBLIC scor, deli, hellp, clock, esca, delee, head, stat, safe
  961.    PUBLIC exac, bell, near
  962.    scor  = SET("SCOREBOARD")
  963.    deli  = SET("DELIMITERS")
  964.    hellp = SET("HELP")
  965.    clock = SET("CLOCK")
  966.    esca  = SET("ESCAPE")
  967.    delee = SET("DELETED")
  968.    head  = SET("HEADING")
  969.    stat  = SET("STATUS")
  970.    safe  = SET("SAFETY")
  971.    exac  = SET("EXACT")
  972.    bell  = SET("BELL")
  973.    near  = SET("NEAR")
  974.  
  975.    * Set database environment for applications
  976.    SET SCOREBOARD off
  977.    SET DELIMITERS off
  978.    SET HELP    off
  979.    SET CLOCK   off
  980.    SET ESCAPE  on && off
  981.    SET DELETED on
  982.    SET HEADING on
  983.    SET STATUS  off
  984.    SET SAFETY  off
  985.    SET TALK    off
  986.    SET EXACT   off
  987.    SET BELL    off
  988.    SET NEAR    off
  989.    PUBLIC erased, not_valid, rec_is_dup, filters_on, lookup_ok, choice
  990.    PUBLIC record_num, net_choice
  991.    PUBLIC target, look_dbf, matchchar, scanfield
  992.    * Logical variables used for status flags
  993.    STORE .F. TO  erased, not_valid, rec_is_dup, filters_on
  994.    lookup_ok = .T.
  995.    * Other variables
  996.    STORE "" TO choice,subset
  997.    STORE 0 TO record_num, net_choice
  998.    ************************************************
  999.    * Setup error processing if running on a network
  1000.    IF NETWORK()
  1001.       * Network programming assumes databases have been CONVERTed
  1002.       SET EXCLUSIVE off
  1003.       ON ERROR DO Net_err WITH ERROR()
  1004.       * Retry a reasonable amount of time (depends on computer)
  1005.       SET REPROCESS TO 3
  1006.    ELSE
  1007.       ON ERROR DO Gen_err WITH ERROR(), MESSAGE()
  1008.    ENDIF
  1009.  
  1010. RETURN
  1011.  
  1012. PROCEDURE Gen_Err
  1013. PARAMETERS pn_Error, pc_Message
  1014.    DO Err_Box WITH pc_Message
  1015.    gl_Error = .T.
  1016.    ON ERROR
  1017.    ON KEY LABEL F1
  1018.    ON KEY LABEL F9
  1019.    ON KEY LABEL F10
  1020. RETURN TO MASTER
  1021.  
  1022. *   IF TYPE( "gl_MainMenu" ) <> "L"
  1023. *      DO Rest_env                          && environment back.
  1024. *      ON ERROR
  1025. *      ON KEY LABEL F1
  1026. *      ON KEY LABEL F9
  1027. *      ON KEY LABEL F10
  1028. *      CLEAR ALL
  1029. *      CLOSE ALL
  1030. *      CLEAR
  1031. *      CANCEL
  1032. *   ENDIF
  1033. *RETURN TO MASTER
  1034.  
  1035. PROCEDURE Sho_look
  1036.    PARAMETERS db
  1037.    * Show lookup function keys on screen (if available for database)
  1038.    DO CASE
  1039.       CASE db = "EMPLOYEE" .OR. db = "CUST" .OR. db = "VENDORS"
  1040.          look_txt = "Press F9 to look up Area code"
  1041.       CASE db = "GOODS"
  1042.          look_txt = "Press F9 to look up Vendor name and phone"
  1043.       CASE db = "ORDERS"
  1044.          look_txt = "Press F9 to look up Cust data; F10 for Part ID data"
  1045.       CASE db = "ACCT_REC"
  1046.          look_txt = "Press F9 to look up Customer name and phone"
  1047.    ENDCASE
  1048.    @ 0,0 SAY look_txt COLOR &c_blink.
  1049.    i = INKEY(1)                                  && Blink for 1 second
  1050.    @ 0,0 SAY look_txt COLOR &c_yellow.
  1051. RETURN
  1052.  
  1053. PROCEDURE Show_msg
  1054.    PARAMETERS u_message
  1055.    _wrap = .T.
  1056.    ACTIVATE WINDOW alert
  1057.       @ 1,0 SAY u_message
  1058.       ?
  1059.       WAIT " Press spacebar to continue..."
  1060.    DEACTIVATE WINDOW alert
  1061. RETURN
  1062.  
  1063. PROCEDURE Skip_rec
  1064.    PARAMETERS skipno
  1065.    * Skip forward or backward in database by one or more records
  1066.    DO CASE
  1067.    CASE skipno = 1         && Skip to next record (in active index order)
  1068.       IF .NOT. EOF()
  1069.          SKIP
  1070.       ENDIF
  1071.    CASE skipno = -1        && Skip to previous record (in active index order)
  1072.       IF .NOT. BOF()
  1073.          SKIP -1
  1074.       ENDIF
  1075.    CASE skipno = 0
  1076.       * Skip records - to goto/view records ahead of or behind current record
  1077.       numb_2skip = 0
  1078.       ACTIVATE WINDOW alert
  1079.          @ 0,0 SAY "-------- SKIP NUMBER OF RECORDS ----------"
  1080.          @ 2,1 SAY "How many records do you want to skip?"
  1081.          @ 3,0 SAY "   (Example: 15 or -5) ?   " ;
  1082.                GET numb_2skip PICTURE "9999" ;
  1083.                MESSAGE "Enter positive no. to go forward " + ;
  1084.                        "or negative no. to go backward"
  1085.          READ
  1086.       DEACTIVATE WINDOW alert
  1087.       IF .NOT. (BOF() .AND. numb_2skip < 0) .OR. (EOF() .AND. numb_2skip > 0)
  1088.          SKIP numb_2skip
  1089.       ENDIF
  1090.    ENDCASE
  1091.  
  1092.    * Check whether record pointer hits beginning or end of file
  1093.    DO CASE
  1094.       CASE EOF()
  1095.          GO BOTTOM                  && reset record pointer if EOF
  1096.          DO Show_msg WITH " Bottom record in " + dbf + " database"
  1097.       CASE BOF()
  1098.          DO Show_msg WITH " Top record in " + dbf + " database"
  1099.    ENDCASE
  1100. RETURN
  1101.  
  1102. PROCEDURE Warnbell
  1103.    PRIVATE mwrap
  1104.    mwrap = _wrap           && Save _wrap value
  1105.    _wrap = .F.
  1106.    * Sound unique warning for errors
  1107.    SET BELL TO 880,4
  1108.    ?? CHR(7)
  1109.    SET BELL TO 1400,4
  1110.    ?? CHR(7)
  1111.    SET BELL TO 880,4
  1112.    ?? CHR(7)
  1113.    SET BELL TO
  1114.    _wrap = mwrap
  1115. RETURN
  1116.  
  1117.  
  1118. FUNCTION NodShake
  1119. PARAMETERS pc_mssg, pn_up, pn_left, pn_height, pn_max, pl_dflt_no
  1120. *---------------------------------------------------------------------------
  1121. * NAME
  1122. *   NodShake
  1123. *
  1124. * DESCRIPTION
  1125. *   Accepts a YES/NO response from user
  1126. *
  1127. * SYNOPSIS
  1128. *   DO _NodShake WITH pc_mssg, pn_up, pn_left, pn_height, pn_max, pl_dflt_no
  1129. *
  1130. * PARAMETERS
  1131. *   pc_mssg:    dialog box message
  1132. *   pn_up:      upper corrdinate of dialog box
  1133. *   pn_left:    left coordinate of dialog box
  1134. *   pn_height:  height of dialog box
  1135. *   pn_max:     maximum width of a line in message
  1136. *   pl_dflt_no: flag indicating if default pad highlighted should be "NO"
  1137. *       
  1138. * EXAMPLE
  1139. *    pl_set = _NodShake( pc_vermssg, 13, 25, 2, 28, .T. )
  1140. *       
  1141. * LIMITATIONS
  1142. *   None
  1143. *
  1144. * DEPENDENCIES
  1145. *   None
  1146. *---------------------------------------------------------------------------
  1147.  
  1148.   PRIVATE ll_ans, ll_console, ll_wrapset, ln_pspset
  1149.  
  1150.   ll_console = SET( "CONSOLE" ) = "OFF"
  1151.   SET CONSOLE ON
  1152.   ll_wrapset = _wrap
  1153.   ln_pspset = _pspacing
  1154.   _wrap = .F.
  1155.   _pspacing = 1
  1156.  
  1157.   DEFINE WINDOW NodShake DOUBLE ;
  1158.      FROM pn_up, pn_left TO pn_up + pn_height + 4, pn_left + pn_max + 1
  1159.  
  1160.   DEFINE MENU NodShake
  1161.   DEFINE PAD Yes OF NodShake PROMPT "Yes" ;
  1162.      AT pn_height + 1, (pn_max - 12) / 2;
  1163.      MESSAGE "Select option and press ENTER, or press first letter" + ;
  1164.              " of desired option"
  1165.  
  1166.   ON SELECTION PAD Yes OF NodShake DEACTIVATE MENU
  1167.   DEFINE PAD No OF NodShake PROMPT "No" ;
  1168.      AT pn_height + 1, (pn_max - 12) / 2 + 10 ;
  1169.      MESSAGE "Select option and press ENTER, or press first letter" + ;
  1170.              " of desired option"
  1171.  
  1172.   ON SELECTION PAD No OF NodShake DEACTIVATE MENU
  1173.   ACTIVATE WINDOW NodShake
  1174.   CLEAR
  1175.   ?
  1176.   @ 0, 0
  1177.   ?? pc_mssg FUNCTION ";"
  1178.  
  1179.   ON KEY LABEL Y KEYBOARD "{Alt-Y}{13}"
  1180.   ON KEY LABEL N KEYBOARD "{Alt-N}{13}"
  1181.  
  1182.   IF pl_dflt_no
  1183.     KEYBOARD "{Alt-N}"
  1184.   ENDIF
  1185.  
  1186.   ON KEY LABEL RIGHTARROW
  1187.   ON KEY LABEL LEFTARROW
  1188.  
  1189.   ACTIVATE MENU NodShake
  1190.  
  1191.   ON KEY LABEL Y
  1192.   ON KEY LABEL N
  1193.  
  1194.   IF PAD() = "YES"
  1195.     ll_ans = .T.
  1196.   ELSE
  1197.     ll_ans = .F.
  1198.   ENDIF
  1199.  
  1200.   RELEASE WINDOW NodShake
  1201.   RELEASE MENU NodShake
  1202.   _wrap = ll_wrapset
  1203.   _pspacing = ln_pspset
  1204.  
  1205.   IF ll_console
  1206.     SET CONSOLE OFF
  1207.   ENDIF
  1208.  
  1209. RETURN ll_ans
  1210. *-- EOF: NodShake( pc_mssg, pn_up, pn_left, pn_height, pn_max, pl_dflt_no )
  1211.  
  1212. PROCEDURE Err_Box
  1213. PARAMETERS pc_msg
  1214. *----------------------------------------------------------------------------
  1215. * NAME
  1216. *   Err_Box - Display an error box
  1217. *
  1218. * SYNOPSIS
  1219. *   DO Err_Box WITH <pc_msg>
  1220. *
  1221. * DESCRIPTION
  1222. *   _Err_Box will display the <pc_msg> string in a box and prompt the
  1223. *   user to press any key to continue processing.  _Err_Box will display
  1224. *   the message based on the length of <pc_msg>.
  1225. *
  1226. * PARAMETERS
  1227. *   pc_msg - the error message to display in the box.  If the length is
  1228. *            greater than 76, the trailing part is chopped off.
  1229. *
  1230. * EXAMPLE
  1231. *   DO Err_Box WITH "Incorrect window size"
  1232. *   Displays the message in a window as follows at row 9 on the screen:
  1233. *                      +------------------------------+
  1234. *                      |                              |
  1235. *                      |    Incorrect window size     |
  1236. *                      |                              |
  1237. *                      | Press any key to continue... |
  1238. *                      |                              |
  1239. *                      +------------------------------+
  1240. *   Note that the width of the window will increase to accommodate a longer
  1241. *   message string.
  1242. *
  1243. * LIMITATIONS
  1244. *   Truncates the message after 76 characters.  Assumes an 80 character
  1245. *   wide screen.  Looks best with SET CURSOR OFF.
  1246. *
  1247. *----------------------------------------------------------------------------
  1248.  
  1249.   PRIVATE lc_anykey, lc_msg, lc_msglen, lc_win, ln_press, ln_width, ll_trap,;
  1250.           ll_escape
  1251.  
  1252.   lc_anykey = [Press any key to continue...]
  1253.   ln_press  = LEN( lc_anykey )
  1254.   lc_win = WINDOW()                     && Currently activated window if any
  1255.   lc_msg = LTRIM( RTRIM( pc_msg ) )     && Trimmed message
  1256.   ln_msglen = LEN( lc_msg )             && Trimmed length of message
  1257.   ln_width = 0                          && Width of display area in window.
  1258.   ll_escape = SET("ESCAPE") = "ON"
  1259.   SET ESCAPE OFF
  1260.  
  1261.   *-- Determine the width needed for the window:
  1262.   IF ln_msglen <= ln_press
  1263.     ln_width = ln_press
  1264.   ELSE
  1265.     *-- Make sure the message fits in the window:
  1266.     IF ln_msglen > 76
  1267.       lc_msg = LEFT( lc_msg, 76 )
  1268.       ln_msglen = 76
  1269.     ENDIF
  1270.     ln_width = ln_msglen
  1271.   ENDIF
  1272.   DEFINE WINDOW _err_box FROM 9, ((76 - ln_width) + .5) / 2 ;
  1273.                 TO 15, (ln_width + 83) / 2 DOUBLE
  1274.   ln_width = ( ln_width + 2 )
  1275.  
  1276.   *-- Display the message and prompt to the window and wait for a key press
  1277.   ACTIVATE WINDOW _err_box
  1278.   @ 1, ( ln_width - ln_msglen ) / 2 SAY lc_msg
  1279.   @ 3, ( ln_width - ln_press ) / 2 SAY lc_anykey
  1280.   SET CONSOLE OFF                       && For mouse click recognition
  1281.   WAIT
  1282.   SET CONSOLE ON
  1283.  
  1284.   *-- Clean up the window display and reactivate the previous window
  1285.   RELEASE WINDOW _err_box
  1286.   IF ISBLANK( lc_win )
  1287.     ACTIVATE SCREEN
  1288.   ENDIF
  1289.  
  1290.   IF ll_escape
  1291.     SET ESCAPE ON
  1292.   ELSE
  1293.     SET ESCAPE OFF
  1294.   ENDIF
  1295.  
  1296. RETURN
  1297. *-- EOP: Err_Box WITH pc_msg
  1298.  
  1299. PROCEDURE Colo_rese
  1300. PRIVATE old_color, c_messages, c_titles, c_box, c_info, c_fields
  1301.  
  1302. old_color = c_save
  1303.  
  1304. * Set the Primary colors
  1305. SET COLOR TO
  1306. SET COLOR TO &old_color.
  1307. CLEAR
  1308.  
  1309. * Remove primary colors and start at the secondary colors
  1310. old_color = STUFF(old_color, 1, AT("&",old_color)+2, "")
  1311.  
  1312. comma = AT(",",old_color)
  1313. c_messages = LEFT(old_color, comma-1)        && Get MESSAGES color
  1314. old_color = STUFF(old_color, 1, comma, "")    && Remove MESSAGES color
  1315.  
  1316. comma = AT(",",old_color)
  1317. c_titles = LEFT(old_color, comma-1)        && Get TITLES color
  1318. old_color = STUFF(old_color, 1, comma, "")    && Remove TITLES color
  1319.  
  1320. comma = AT(",",old_color)
  1321. c_box = LEFT(old_color, comma-1)        && Get BOX color
  1322. old_color = STUFF(old_color, 1, comma, "")    && Remove BOX color
  1323.  
  1324. comma = AT(",",old_color)
  1325. c_info = LEFT(old_color, comma-1)        && Get INFORMATION color
  1326. old_color = STUFF(old_color, 1, comma, "")    && Remove INFORMATION color
  1327.  
  1328. comma = AT(",",old_color)
  1329. c_fields = old_color                && Get FIELDS color
  1330.  
  1331. SET COLOR OF MESSAGES    TO &c_messages.
  1332. SET COLOR OF TITLES      TO &c_titles.
  1333. SET COLOR OF BOX         TO &c_box.
  1334. SET COLOR OF INFORMATION TO &c_info.
  1335. SET COLOR OF FIELDS      TO &c_fields.
  1336. RETURN
  1337.  
  1338. **************************** END OF LIBRARY.PRG ******************************
  1339.  
  1340.  
  1341.  
  1342.